package servlet;

import controller.ControllerLoginLocal;
import controller.ControllerProfiloLocal;
import controller.ControllerUtentiLocal;
import eccezioni.UtenteBannatoException;
import eccezioni.UtenteNonTrovatoException;
import eccezioni.UtenteNonVerificatoException;
import entity.Adesione;
import entity.UtenteRegistrato;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import statefulSB.UtenteLoggato.StatoIscrizione;
import statefulSB.UtenteLoggatoLocal;
import utilities.Utilities;
import static utilities.Utilities.*;
import utilities.json.JSONException;
import utilities.json.JSONObject;
import utilities.json.JSONReader;

/**
 * Servlet per la comunicazione con Facebook.
 * @author fabio
 */
public class FbServlet extends HttpServlet {
    @EJB
    private ControllerProfiloLocal controllerProfilo;
    @EJB
    private ControllerLoginLocal controllerLogin;

    @EJB
    private ControllerUtentiLocal controllerUtenti;
    
    /**
     * Processes requests for both HTTP
     * <code>GET</code> and
     * <code>POST</code> methods.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = null;
        try {
            out = response.getWriter();
        } catch (IOException ex) {
            Logger.getLogger(FbServlet.class.getName()).log(Level.SEVERE, null, ex);
        }


        String action = request.getParameter("action");
        String token;
        if (action == null) {
             Utilities.errore("Nessuna action specificata alla FbServlet", request, response);
        } else if (action.equals("registerFb")) {
            String code = request.getParameter("code");
            if (code == null) {
                String s = "https://www.facebook.com/dialog/oauth?"
                        + "client_id=203084123120887&"
                        + "redirect_uri=http://localhost:8080/ShippingShareBisBis-war/Controller?action=registerFb&"
                        + "scope=email,publish_stream";
                response.sendRedirect(s);
            } else {
                String url = "https://graph.facebook.com/oauth/access_token?"
                        + "client_id=203084123120887&"
                        + "redirect_uri=http://localhost:8080/ShippingShareBisBis-war/Controller?action=registerFb&"
                        + "client_secret=320da5da426cd45fa8cc59c2a8c52c3e&"
                        + "code=" + code;
                token = readFromUrl(url);
                url = "https://graph.facebook.com/me?" + token;
                JSONObject reply;
                try {
                    reply = JSONReader.readJSONFromUrl(url);
                    String id = reply.getString("id");
                    String name = reply.getString("first_name");
                    String surname = reply.getString("last_name");
                    String email = reply.getString("email");
                    out.println("id: " + id + ", nome: " + name + ", cognome: " + surname + ", email: " + email);
                    request.setAttribute("email", email);
                    request.setAttribute("nome", name);
                    request.setAttribute("cognome", surname);
                    request.setAttribute("id", id);
                    forward("/registrazioneUtenteSocial.jsp", request, response);

                } catch (JSONException ex) {
                    Logger.getLogger(FbServlet.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        } else if (action.equals("loginFb")) {
            // token = getToken(request, response);
            String code = request.getParameter("code");
            if (code == null) {
                String s = "https://www.facebook.com/dialog/oauth?"
                        + "client_id=203084123120887&"
                        + "redirect_uri=http://localhost:8080/ShippingShareBisBis-war/Controller?action=loginFb&"
                        + "scope=email,publish_stream";
                response.sendRedirect(s);
            } else {
                String url = "https://graph.facebook.com/oauth/access_token?"
                        + "client_id=203084123120887&"
                        + "redirect_uri=http://localhost:8080/ShippingShareBisBis-war/Controller?action=loginFb&"
                        + "client_secret=320da5da426cd45fa8cc59c2a8c52c3e&"
                        + "code=" + code;
                token = readFromUrl(url);
                url = "https://graph.facebook.com/me?" + token;
                token = token.split("=")[1].split("&")[0];
                String email = "";
                JSONObject reply;
                try {
                    reply = JSONReader.readJSONFromUrl(url);
                    email = reply.getString("email");
                    String id = reply.getString("id");
                    UtenteRegistrato ur = controllerLogin.loginOpenId(email);
                    controllerProfilo.setFacebookId(ur, id);
                    UtenteLoggatoLocal ull = (UtenteLoggatoLocal) (new InitialContext()).lookup("java:global/ShippingShareBisBis/ShippingShareBisBis-ejb/UtenteLoggato!statefulSB.UtenteLoggatoLocal");
                    ull.setIdUtente(ur.getId());
                    ull.setAdesioniInCorso(new LinkedList<Adesione>());
                    ull.setStatoIscrizione(StatoIscrizione.NESSUNO);
                    ull.setFacebookToken(token);
                    HttpSession session = request.getSession();
                    session.setAttribute("utenteLoggato", ull);
                    response.sendRedirect("index.jsp");
                } catch (NamingException ex) {
                    Logger.getLogger(FbServlet.class.getName()).log(Level.SEVERE, null, ex);
                } catch (UtenteNonTrovatoException unte) {
                    errore(unte.getMessage(), request, response);
                } catch (UtenteBannatoException ube) {
                    errore(ube.getMessage(), request, response);
                } catch (JSONException ex) {
                    Logger.getLogger(FbServlet.class.getName()).log(Level.SEVERE, null, ex);
                } catch (UtenteNonVerificatoException unve) {
                    errore(unve.getMessage(), request, response);
                }
            }
        } else if (action.equals("postFb")) {
            String msg = request.getParameter("messaggio");
            String redi = request.getParameter("redirect");
            UtenteLoggatoLocal ul = utilities.Utilities.getUtenteLoggatoLocal(request);
            if(ul==null){
                utilities.Utilities.errore("Non hai effettuato il login.", request, response);
            }
            token = ul.getFacebookToken();
            if (token == null) {
                utilities.Utilities.errore("Non risulti essere collegato a facebook.", request, response);

            } else {
                //   request.setAttribute("access_token", token);
                //   request.setAttribute("message",msg);
                //   request.setAttribute("link","http://localhost:8080/ShippingShareBisBis-war");
                String params = "message=" + msg;
                String u = "https://graph.facebook.com/me/feed&access_token=" + token;
                URL url = new URL(u);
                URLConnection uc = url.openConnection();
                uc.setDoOutput(true);
                OutputStreamWriter writer = new OutputStreamWriter(uc.getOutputStream());
                writer.write(params);
                writer.flush();
                StringBuilder answer = new StringBuilder();
                BufferedReader reader = new BufferedReader(new InputStreamReader(uc.getInputStream()));
                String line;
                while ((line = reader.readLine()) != null) {
                    answer.append(line);
                }
                writer.close();
                reader.close();

                // Output the response
                // System.out.println(answer.toString());
                if(redi!=null) utilities.Utilities.forward(redi, request, response);
            }

        } else if (action.equals("tokenFb")) {
            String code = request.getParameter("code");
            if (code == null) {
                String s = "https://www.facebook.com/dialog/oauth?"
                        + "client_id=203084123120887&"
                        + "scope=email,read_friendlists&"
                        + "redirect_uri=http://localhost:8080/ShippingShareBisBis-war/Controller?action=tokenFb";
                response.sendRedirect(s);
            } else {
                String url = "https://graph.facebook.com/oauth/access_token?"
                        + "client_id=203084123120887&"
                        + "client_secret=320da5da426cd45fa8cc59c2a8c52c3e&"
                        + "code=" + code;
                token = readFromUrl(url).split("=")[1].split("&")[0];
                out.write(token);
            }


        } else if (action.equals("linkFb")) {
            String code = request.getParameter("code");
            String redirect = request.getParameter("redirect");
            String state = request.getParameter("state");
            if (state != null) {
                redirect = state;
            }
            if (code == null) {
                String s = "https://www.facebook.com/dialog/oauth?"
                        + "client_id=203084123120887&"
                        + "scope=email,read_friendlists&"
                        + "redirect_uri=http://localhost:8080/ShippingShareBisBis-war/Controller?action=linkFb"
                        + "&state=" + redirect;

                response.sendRedirect(s);
            } else {
                try {
                    String url = "https://graph.facebook.com/oauth/access_token?"
                            + "client_id=203084123120887&"
                            + "client_secret=320da5da426cd45fa8cc59c2a8c52c3e&"
                            + "code=" + code
                            + "&redirect_uri=http://localhost:8080/ShippingShareBisBis-war/Controller?action=linkFb"
                            + "&state=" + redirect;
                    token = readFromUrl(url).split("=")[1].split("&")[0];
                    utilities.Utilities.getUtenteLoggatoLocal(request).setFacebookToken(token);
                    url = "https://graph.facebook.com/me?access_token=" + token;
                    JSONObject reply;
                    reply = JSONReader.readJSONFromUrl(url);
                    String id = reply.getString("id");
                    controllerProfilo.setFacebookId(utilities.Utilities.getUtenteLoggato(request), id);

                    response.sendRedirect(redirect);
                } catch (JSONException ex) {
                    Logger.getLogger(FbServlet.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
    }

    /**
     * Restituisce la stringa letta dal {@link Reader} in input
     * @param rd {@link Reader} da cui leggere
     * @return la stringa letta
     * @throws IOException
     */
    public static String readAll(Reader rd) throws IOException {
        StringBuilder sb = new StringBuilder();
        int cp;
        while ((cp = rd.read()) != -1) {
            sb.append((char) cp);
        }
        return sb.toString();
    }

    /**
     * Restituisce la stringa letta dall'{@link URL} in input
     * @param url {@link URL} da cui leggere
     * @return la stringa letta
     * @throws IOException
     */
    public static String readFromUrl(String url) throws IOException {
        InputStream is = new URL(url).openStream();
        try {
            BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
            return readAll(rd);
        } finally {
            is.close();
        }
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /**
     * Handles the HTTP
     * <code>GET</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Handles the HTTP
     * <code>POST</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Returns a short description of the servlet.
     *
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>
    
}
